package com.gframework.boot.mvc.filter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.core.annotation.Order;
import org.springframework.web.filter.OncePerRequestFilter;

import com.gframework.boot.mvc.filter.ClickHijackSafeFilter.ClickHijackSafeProperties;

/**
 * 一个用于处理点击劫持攻击的过滤器.
 * <p>
 * <strong>点击劫持</strong><br>
 * 点击劫持是通过在一个精心设计的页面上放入几个透明的iframe，并且位置在按钮上，在用户点击时会触发相应操作。
 * 这包括点击劫持，拖拽劫持，图片覆盖等问题。<br>
 * 解决方案是通过<code>X-Frame-Options</code>响应头来控制页面是否允许被嵌入iframe。<br>
 * 这个响应头有三个可选值
 * <ul>
 * <li>DENY：页面不能被嵌入到任何iframe或frame中；</li>
 * <li>SAMEORIGIN：页面只能被本站页面嵌入到iframe或者frame中</li>
 * <li>ALLOW-FROM：页面允许iframe或frame加载</li>
 * </ul>
 * 
 * @since 2.0.0
 * @author Ghwolf
 * @see CSRFErrorProcessor
 */
@ConditionalOnProperty(value = "gframework.mvc.filter.click-hijack.enabled", havingValue = "true",matchIfMissing = true)
@EnableConfigurationProperties(ClickHijackSafeProperties.class)
@Order(Integer.MIN_VALUE - 100_000)
public class ClickHijackSafeFilter extends OncePerRequestFilter {

	
	@ConfigurationProperties("gframework.mvc.filter.click-hijack")
	static class ClickHijackSafeProperties {
		/**
		 * 是否开启点击劫持安全过滤器，默认开启(true)
		 */
		private boolean enabled = true;
		
		public boolean isEnabled() {
			return this.enabled;
		}

		public void setEnabled(boolean enabled) {
			this.enabled = enabled;
		}
	}
	
	public ClickHijackSafeFilter(){
		logger.info("====> 以启用 ClickHijackSafeFilter 安全过滤器，用于处理 点击劫持 安全问题。");
	}

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {
		response.addHeader("X-Frame-Options", "SAMEORIGIN");
		filterChain.doFilter(request, response);
	}

}
